//
//  UFilesystem.cpp
//  UltraStarDeluxeIOS
//
//  Created by 李 杰军 on 12-7-15.
//  Copyright (c) 2012年 DoReiMi. All rights reserved.
//

#include <iostream>

#include "UFilesystem.h"
#include "USearchOps.h"

TFilesystem* FileSystem = NULL;

std::vector<std::string>* TFilesystem::list(const std::string& path, const std::string& pattern, bool recursive, bool dirs)
{
    // directory change requires locking due to saved returns
    std::vector<std::string>* ret = new std::vector<std::string>();
    
    
    findFiles(path, pattern, recursive, dirs, ret, 0);
    
    return ret;
}

void TFilesystem::findFiles(const std::string& path, const std::string& pattern, bool recursive, bool dirs, std::vector<std::string> *simpleList, FileInfoList *detailList) const
{
    intptr_t lHandle, res;
    struct _finddata_t tagData;
    
    // pattern can contain a directory name, separate it from mask
    size_t pos1 = pattern.rfind ('/');
    size_t pos2 = pattern.rfind ('\\');
    if (pos1 == pattern.npos || ((pos2 != pattern.npos) && (pos1 < pos2)))
        pos1 = pos2;
    std::string directory;
    if (pos1 != pattern.npos)
        directory = pattern.substr (0, pos1 + 1);
    
    std::string full_pattern = path + pattern;
    
    lHandle = _findfirst(full_pattern.c_str(), &tagData);
    res = 0;
    while (lHandle != -1 && res != -1)
    {
        if ((dirs == ((tagData.attrib & _A_SUBDIR) != 0)) &&
            ( /*!msIgnoreHidden ||*/ (tagData.attrib & _A_HIDDEN) == 0 ) &&
            (!dirs/* || !is_reserved_dir (tagData.name)*/))
        {
            if (simpleList)
            {
                simpleList->push_back(directory + tagData.name);
            }
        }
        res = _findnext( lHandle, &tagData );
    }
    
    // Close if we found any files
    if(lHandle != -1)
        _findclose(lHandle);
    
    // Now find directories
    if (recursive)
    {
        std::string base_dir = path;
        if (!directory.empty ())
        {
            base_dir = path + directory;
            // Remove the last '/'
            base_dir.erase (base_dir.length () - 1);
        }
        
        base_dir.append ("/*");
        // Remove directory name from pattern
        std::string mask ("/");
        if (pos1 != pattern.npos)
            mask.append (pattern.substr (pos1 + 1));
        else
            mask.append (pattern);

        lHandle = _findfirst(base_dir.c_str (), &tagData);
        res = 0;
        while (lHandle != -1 && res != -1)
        {
            if ((tagData.attrib & _A_SUBDIR) &&
                ( /*!msIgnoreHidden ||*/ (tagData.attrib & _A_HIDDEN) == 0 ) /*&&
                !is_reserved_dir (tagData.name)*/)
            {
                // recurse
                base_dir = directory;
                base_dir.append (tagData.name).append (mask);
                findFiles(path, base_dir, recursive, dirs, simpleList, detailList);
            }
            res = _findnext( lHandle, &tagData );
        }
        
        // Close if we found any files
        if(lHandle != -1)
            _findclose(lHandle);
    }
}
